#ifndef SF_STRING_H
#define SF_STRING_H

#include <vector>
#include <list>
#include <string>
#include <memory>

/**
 * @brief The SFString class
 * @details 模拟实现Qt SFString类
 *      这样代码方面进行重构时这部分相关功能就只要基于std::string实现就行了
 */
class SFStringList;
class SFStringVector;
class SFString : public std::string
{
public:
    SFString();
    // 表示初始化的字符串,申请size长度, reserve仅仅取消默认构造
    SFString(int size, int reserve);
    SFString(const char *str);
    SFString(const char *str, int len);
    SFString(std::string const &str);

    bool contains(char ch);
    bool contains(const SFString &str);
    bool isValid() const;

    SFStringList split(char ch);
    SFStringList split(char ch) const;
    SFStringList split(SFString const &str);
    SFStringList split(SFString const &str) const;

    SFStringVector splitv(char ch);
    SFStringVector splitv(char ch) const;
    SFStringVector splitv(SFString const &str);
    SFStringVector splitv(SFString const &str) const;

    SFString arg(const SFString &a, int fieldWidth = 0, char fillChar = ' ') const;
    SFString arg(const SFString &a1, const SFString &a2) const;
    SFString arg(const SFString &a1, const SFString &a2, const SFString &a3) const;

    // 直接转换成字符串调用上面的函数就行了
    SFString arg(int a, int fieldWidth = 0, int base=10, char fillChar = ' ') const
    {
        return arg(number(a, base), fieldWidth, fillChar);
    }
    SFString arg(unsigned int a, int fieldWidth = 0, int base=10, char fillChar = ' ') const
    {
        return arg(number(a, base), fieldWidth, fillChar);
    }

    SFString arg(long a, int fieldWidth = 0, int base=10, char fillChar = ' ') const
    {
        return arg(number(a, base), fieldWidth, fillChar);
    }
    SFString arg(unsigned long a, int fieldWidth = 0, int base=10, char fillChar = ' ') const
    {
        return arg(number(a, base), fieldWidth, fillChar);
    }

    SFString arg(long long a, int fieldWidth = 0, int base=10, char fillChar = ' ') const
    {
        return arg(number(a, base), fieldWidth, fillChar);
    }

    SFString arg(unsigned long long a, int fieldWidth = 0, int base=10, char fillChar = ' ') const
    {
        return arg(number(a, base), fieldWidth, fillChar);
    }

    SFString arg(double a, int fieldWidth = 0, char fmt = 'g', int prec = -1, char fillChar = ' ') const
    {
        return arg(number(a, fmt, prec), fieldWidth, fillChar);
    }

    static SFString number(int, int base=10);
    static SFString number(unsigned int, int base=10);
    static SFString number(long, int base=10);
    static SFString number(unsigned long, int base=10);
    static SFString number(long long, int base=10);
    static SFString number(unsigned long long, int base=10);
    static SFString number(double, char f='g', int prec=6);

    bool                toBool(bool def = false);
    unsigned int        toUInt(unsigned int def = 0, int scale = 10) const;
    int                 toInt(int def = 0, int scale = 10) const;
    long                toLong(long def = 0, int scale = 10) const;
    unsigned long       toULong(unsigned long def = 0, int scale = 10) const;
    float               toFloat(float def = 0) const;
    double              toDouble(double def = 0) const;
    long long           toLongLong(long long def = 0, int scale = 10) const;
    unsigned long long  toULongLong(unsigned long long def = 0, int scale = 10) const;

    bool isEmpty() const;
    const std::string &toStdString() const;

    SFString trimmed();
    SFString trimmed() const;
    SFString simplified();
    SFString simplified() const;

    SFString basename();
    SFString basename() const
    {
        return const_cast<SFString *>(this)->basename();
    }
    SFString dirname();
    SFString dirname() const
    {
        return const_cast<SFString *>(this)->dirname();
    }
    //! 截取字符，从i开始，pos结束，-1表示直接到达末尾位置
    SFString mid(int i, int pos = -1);

    bool equals(const SFString &str)
    {
        return *this == str;
    }
    bool equals(const SFString &str) const
    {
        return *this == str;
    }

    void toUpper();
    void toLower();

    static SFString format(const char *fmt, ...);
private:
    SFString multiArg(int numArgs, const SFString **args) const;
};

inline bool SFString::isEmpty() const { return this->empty(); }

inline const std::string &SFString::toStdString() const { return *this; }

class SFStringList : public std::list<SFString>
{
public:
    int count() const { return this->size(); }
    void append(const SFString &str)
    {
        this->push_back(str);
    }
    bool contain(const SFString &str)
    {
        for (const SFString &s : *this)
        {
            if (s == str)
            {
                return true;
            }
        }
        return false;
    }
    SFString at(int i)
    {
        SFString ret;
        int _i = 0;
        for (const SFString &s : *this)
        {
            if (i == _i)
            {
                return s;
            }
        }
        return "";
    }
    SFString at(int i) const
    {
        return const_cast<SFStringList *>(this)->at(i);
    }
};
class SFStringVector : public std::vector<SFString>
{
public:
    int count() const { return this->size(); }
    void append(const SFString &str)
    {
        this->push_back(str);
    }
    bool contain(const SFString &str)
    {
        for (const SFString &s : *this)
        {
            if (s == str)
            {
                return true;
            }
        }
        return false;
    }
    int length() const { return this->size(); }
};
class SFByteArray : public SFString
{
public:
    SFByteArray() {}
    SFByteArray(int size, int reserve)
        : SFString(size, reserve)
    {}
    SFByteArray(const char *str)
        : SFString(str)
    {}
    SFByteArray(const char *str, int len)
        : SFString(str, len)
    {}
    SFByteArray(std::string const &str)
        : SFString(str)
    {}


    SFByteArray mid(int pos, int len = -1) const;

    SFByteArray toHex() const;
    SFByteArray toHex(char separator) const;

    SFByteArray &remove(int pos, int len);

};


#endif // SF_STRING_H
